home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software of the Month Club 1996 April
/
Software of the Month Club 1996 April.iso
/
pc
/
os2
/
psutils
/
src
/
psutil.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-21
|
9KB
|
336 lines
/* psutil.c
* Copyright (C) Angus J. C. Duggan 1991-1995
* See file LICENSE for details.
*
* utilities for PS programs
*/
/*
* AJCD 6/4/93
* Changed to using ftell() and fseek() only (no length calculations)
* Hunter Goatley 31-MAY-1993 23:33
* Fixed VMS support.
* Hunter Goatley 2-MAR-1993 14:41
* Added VMS support.
*/
#include "psutil.h"
#include "pserror.h"
#include "patchlev.h"
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#define iscomment(x,y) (strncmp(x,y,strlen(y)) == 0)
extern char *program ;
extern int pages;
extern int verbose;
extern FILE *infile;
extern FILE *outfile;
extern char pagelabel[BUFSIZ];
extern int pageno;
static char buffer[BUFSIZ];
static long bytes = 0;
static long pagescmt = 0;
static long headerpos = 0;
static long endsetup = 0;
static long beginprocset = 0; /* start of pstops procset */
static long endprocset = 0;
static int outputpage = 0;
static int maxpages = 100;
static long *pageptr;
/* list of paper sizes supported */
static Paper papersizes[] = {
{ "a3", 842, 1191 }, /* 29.7cm * 42cm */
{ "a4", 595, 842 }, /* 21cm * 29.7cm */
{ "a5", 421, 595 }, /* 14.85cm * 21cm */
{ "b5", 516, 729 }, /* 18.2cm * 25.72cm */
{ "A3", 842, 1191 }, /* 29.7cm * 42cm */
{ "A4", 595, 842 }, /* 21cm * 29.7cm */
{ "A5", 421, 595 }, /* 14.85cm * 21cm */
{ "B5", 516, 729 }, /* 18.2cm * 25.72cm */
{ "letter", 612, 792 }, /* 8.5in * 11in */
{ "legal", 612, 1008 }, /* 8.5in * 14in */
{ "ledger", 1224, 792 }, /* 17in * 11in */
{ "tabloid", 792, 1224 }, /* 11in * 17in */
{ "statement", 396, 612 }, /* 5.5in * 8.5in */
{ "executive", 540, 720 }, /* 7.6in * 10in */
{ "folio", 612, 936 }, /* 8.5in * 13in */
{ "quarto", 610, 780 }, /* 8.5in * 10.83in */
{ "10x14", 720, 1008 }, /* 10in * 14in */
{ NULL, 0, 0 }
};
/* return pointer to paper size struct or NULL */
Paper* findpaper(char *name)
{
Paper *pp;
for (pp = papersizes; PaperName(pp); pp++) {
if (strcmp(PaperName(pp), name) == 0) {
return pp;
}
}
return (Paper *)NULL;
}
/* make a file seekable; trick stolen from Chris Torek's libdvi */
FILE *seekable(FILE *fp)
{
FILE *ft;
long r, w;
char *p;
#if defined(WINNT)
struct _stat fs ;
#endif
#if defined(WINNT)
if (_fstat(fileno(fp), &fs) == 0 && (fs.st_mode&_S_IFREG) != 0)
return (fp);
#else
if (!fseek(fp, 0L, SEEK_CUR))
return (fp);
#endif
#if defined(MSDOS)
message(FATAL, "input is not seekable\n");
return (NULL) ;
#else
if ((ft = tmpfile()) == NULL)
return (NULL);
while ((r = fread(p = buffer, sizeof(char), BUFSIZ, fp)) > 0) {
do {
if ((w = fwrite(p, sizeof(char), r, ft)) == 0)
return (NULL) ;
p += w ;
r -= w ;
} while (r > 0) ;
}
if (!feof(fp))
return (NULL) ;
/* discard the input file, and rewind the temporary */
(void) fclose(fp);
if (fseek(ft, 0L, SEEK_SET) != 0)
return (NULL) ;
return (ft);
#endif
}
/* copy input file from current position upto new position to output file */
static int fcopy(long upto)
{
long here = ftell(infile);
while (here < upto) {
if ((fgets(buffer, BUFSIZ, infile) == NULL) ||
(fputs(buffer, outfile) == EOF))
return(0);
here = ftell(infile);
bytes += strlen(buffer);
}
return (1);
}
/* build array of pointers to start/end of pages */
void scanpages(void)
{
register char *comment = buffer+2;
register int nesting = 0;
register long int record;
if ((pageptr = (long *)malloc(sizeof(long)*maxpages)) == NULL)
message(FATAL, "out of memory\n");
pages = 0;
fseek(infile, 0L, SEEK_SET);
while (record = ftell(infile), fgets(buffer, BUFSIZ, infile) != NULL)
if (*buffer == '%') {
if (buffer[1] == '%') {
if (nesting == 0 && iscomment(comment, "Page:")) {
if (pages >= maxpages-1) {
maxpages *= 2;
if ((pageptr = (long *)realloc((char *)pageptr,
sizeof(long)*maxpages)) == NULL)
message(FATAL, "out of memory\n");
}
pageptr[pages++] = record;
} else if (headerpos == 0 && iscomment(comment, "Pages:"))
pagescmt = record;
else if (headerpos == 0 && iscomment(comment, "EndComments"))
headerpos = ftell(infile);
else if (iscomment(comment, "BeginDocument") ||
iscomment(comment, "BeginBinary") ||
iscomment(comment, "BeginFile"))
nesting++;
else if (iscomment(comment, "EndDocument") ||
iscomment(comment, "EndBinary") ||
iscomment(comment, "EndFile"))
nesting--;
else if (nesting == 0 && iscomment(comment, "EndSetup"))
endsetup = record;
else if (nesting == 0 &&
iscomment(comment, "BeginProcSet: PStoPS"))
beginprocset = record;
else if (beginprocset && !endprocset &&
iscomment(comment, "EndProcSet"))
endprocset = ftell(infile);
else if (nesting == 0 && iscomment(comment, "Trailer")) {
fseek(infile, record, SEEK_SET);
break;
}
} else if (headerpos == 0 && buffer[1] != '!')
headerpos = record;
} else if (headerpos == 0)
headerpos = record;
pageptr[pages] = ftell(infile);
if (endsetup == 0 || endsetup > pageptr[0])
endsetup = pageptr[0];
}
/* seek a particular page */
void seekpage(int p)
{
fseek(infile, pageptr[p], SEEK_SET);
if (fgets(buffer, BUFSIZ, infile) != NULL &&
iscomment(buffer, "%%Page:")) {
char *start, *end;
for (start = buffer+7; isspace(*start); start++);
if (*start == '(') {
int paren = 1;
for (end = start+1; paren > 0; end++)
switch (*end) {
case '\0':
message(FATAL, "Bad page label while seeking page %d\n", p);
case '(':
paren++;
break;
case ')':
paren--;
break;
}
} else
for (end = start; !isspace(*end); end++);
strncpy(pagelabel, start, end-start);
pagelabel[end-start] = '\0';
pageno = atoi(end);
} else
message(FATAL, "I/O error seeking page %d\n", p);
}
/* Output routines. These all update the global variable bytes with the number
* of bytes written */
void writestring(char *s)
{
fputs(s, outfile);
bytes += strlen(s);
}
/* write page comment */
void writepageheader(char *label, int page)
{
if (verbose)
message(LOG, "[%d] ", page);
sprintf(buffer, "%%%%Page: %s %d\n", label, ++outputpage);
writestring(buffer);
}
/* search for page setup */
void writepagesetup(void)
{
char buffer[BUFSIZ];
if (beginprocset) {
for (;;) {
if (fgets(buffer, BUFSIZ, infile) == NULL)
message(FATAL, "I/O error reading page setup %d\n", outputpage);
if (!strncmp(buffer, "PStoPSxform", 11))
break;
if (fputs(buffer, outfile) == EOF)
message(FATAL, "I/O error writing page setup %d\n", outputpage);
bytes += strlen(buffer);
}
}
}
/* write the body of a page */
void writepagebody(int p)
{
if (!fcopy(pageptr[p+1]))
message(FATAL, "I/O error writing page %d\n", outputpage);
}
/* write a whole page */
void writepage(int p)
{
seekpage(p);
writepageheader(pagelabel, p+1);
writepagebody(p);
}
/* write from start of file to end of header comments */
void writeheader(int p)
{
fseek(infile, 0L, SEEK_SET);
if (pagescmt) {
if (!fcopy(pagescmt) || fgets(buffer, BUFSIZ, infile) == NULL)
message(FATAL, "I/O error in header\n");
sprintf(buffer, "%%%%Pages: %d 0\n", p);
writestring(buffer);
}
if (!fcopy(headerpos))
message(FATAL, "I/O error in header\n");
}
/* write prologue to end of setup section excluding PStoPS procset */
int writepartprolog(void)
{
if (beginprocset && !fcopy(beginprocset))
message(FATAL, "I/O error in prologue\n");
if (endprocset)
fseek(infile, endprocset, SEEK_SET);
writeprolog();
return !beginprocset;
}
/* write prologue up to end of setup section */
void writeprolog(void)
{
if (!fcopy(endsetup))
message(FATAL, "I/O error in prologue\n");
}
/* write from end of setup to start of pages */
void writesetup(void)
{
if (!fcopy(pageptr[0]))
message(FATAL, "I/O error in prologue\n");
}
/* write trailer */
void writetrailer(void)
{
fseek(infile, pageptr[pages], SEEK_SET);
while (fgets(buffer, BUFSIZ, infile) != NULL) {
writestring(buffer);
}
if (verbose)
message(LOG, "Wrote %d pages, %ld bytes\n", outputpage, bytes);
}
/* write a page with nothing on it */
void writeemptypage(void)
{
if (verbose)
message(LOG, "[*] ");
sprintf(buffer, "%%%%Page: * %d\n", ++outputpage);
writestring(buffer);
if (beginprocset)
writestring("PStoPSxform concat\n");
writestring("showpage\n");
}